package cn.xz.hfsk.util

import android.content.ContentValues
import android.content.ContentValues.TAG
import android.os.NetworkOnMainThreadException
import android.util.Log
import cn.xz.hfsk.bean.CommonLib
import cn.xz.hfsk.bean.DeviceList
import cn.xz.hfsk.bean.LightOpenDean
import cn.xz.hfsk.net.ControlDevice
import cn.xz.hfsk.net.OkHttpUtil
import okhttp3.Call
import okhttp3.Callback
import okhttp3.Response
import java.io.IOException
import java.net.Socket
import java.net.UnknownHostException
import java.util.*

/**
 * 发送TCP消息*/
object SendTcpUtils {

    fun service(msg: ByteArray, sendI: String, sendP: Int,sendC: String?) {
        if (CommonLib.NEW_ZK){
            if (sendC != null){
                setNewTcp(msg,sendI,sendP,sendC!!)
            }
        }else{
            setTcp(msg,sendI,sendP)
        }
    }

    //新版服务器添加头尾
    private fun setNewTcp(content: ByteArray, ip: String, port: Int, com: String) {
        //新版服务器
        val mData = byteArrayOf(0xb1.toByte(), 0xac.toByte(), 0x00, 0x01, 0x01, (com.toInt() - 1).toByte())
        val a: ByteArray = ControlDevice.addArray(mData, content)
        a[3] = (a.size + 2).toByte() //数组长度
        val l = CRC16Utils.getCrc16(a)
        val b: ByteArray = ControlDevice.addArray(a, l)
        Log.e(ContentValues.TAG,
            "setNewTcp: 12345678->" + ZhuanHuan.bytesToHexString(content) + "---" + ZhuanHuan.bytesToHexString(b
            ) + "--IP-" + ip + "--port--" + port + "----com---" + com
        )
        setTcp(b, ip, port)
    }

    //发送TCP
    private fun setTcp(msg: ByteArray, sendI: String, sendP: Int){
        Thread {
            try {
                val socket = Socket(sendI, sendP)
                // 作用：每隔一段时间检查服务器是否处于活动状态，如果服务器端长时间没响应，自动关闭客户端socket
                // 防止服务器端无效时，客户端长时间处于连接状态
                socket.keepAlive = true
                socket.soTimeout = 800
                try {
                    val outputStream = socket.getOutputStream()
                    outputStream.write(msg)
                    val inputStream = socket.getInputStream()
                    val bytes = ByteArray(32)
                    val len = inputStream.read(bytes)
                    println("客户端收到服务器响应的数据：" + String(bytes, 0, len))
                    outputStream.close()
                    socket.close()
                }catch (e: Exception){
                    e.printStackTrace()
                    println("数据异常-TCP")
                    socket.close()
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }.start()
    }


    interface OnListener {
        fun get(l: ArrayList<LightOpenDean>)
    }

    // 获取灯光开关状态
    fun send(mctAddressNo: Int,mCom: Int,mIP: String,mPort: Int,l1: OnListener) {
        object : Thread() {
            override fun run() {
                //需要在子线程中处理的逻辑
                try {
                    //拼装规则字符串集合
                    val packet = byteArrayOf(0x55.toByte(), 0x01.toByte(), 0x10.toByte(), 0x00.toByte(), 0x00.toByte(), 0x00.toByte(), 0x00.toByte(), 0x66.toByte())
                    packet[1] = mctAddressNo.toByte()
                    packet[7] = (packet[7] + mctAddressNo.toByte() - 1.toByte()).toByte()


                    val mData = byteArrayOf(0xb1.toByte(), 0xac.toByte(),    0x00,0x10      ,0x01    ,mCom.toByte())
                    val a = ControlDevice.addArray(mData, packet)
                    val l = CRC16Utils.getCrc16(a)
                    val msg = ControlDevice.addArray(a, l)

                    Log.e("debug112233-->setStatus:",CRC16Utils.byteTo16String(msg))

                    // 客户端 Socket 可以通过指定 IP 地址或域名两种方式来连接服务器端,实际最终都是通过 IP
                    // 地址来连接服务器
                    // 新建一个Socket，指定其IP地址及端口号
                    val socket = Socket(mIP, mPort)
                    val ops = socket.getOutputStream()
                    //新版中控服务器需要加头和尾
                    if (CommonLib.NEW_ZK){
                        ops.write(msg)
                    }else{
                        ops.write(packet)
                    }

                    val ins = socket.getInputStream()
                    val buf = ByteArray(32)
                    //获取数据赋值
                    while (ins.read(buf) > 0) {
                        Log.e(ContentValues.TAG, "debug112233: 12345678-->${CRC16Utils.byteTo16String(buf)}")

                        //去掉头部，只获取到Data部分
                        val mData = ByteArray(8)
                        System.arraycopy(buf, 6, mData, 0, 8);
                        Log.e(ContentValues.TAG, "debug112233: 12345678--1-->${CRC16Utils.byteTo16String(mData)}")

                        val buf5 = mData[5].toInt() and 0xff
                        val buf6 = mData[6].toInt() and 0xff
                        val states = buf6 + (buf5 shl 8)
                        val groupId = mData[1].toInt()
                        if (groupId == mctAddressNo) {
                            val mStateList: ArrayList<LightOpenDean> = arrayListOf()
                            mStateList.clear()
                            for (i in 0..15) {
                                val state = states shr i and 0x01
                                if (state > 0) {
                                    mStateList.add(LightOpenDean(mctAddressNo,i+1,mCom,true))
                                } else {
                                    mStateList.add(LightOpenDean(mctAddressNo,i+1,mCom,false))
                                }
                            }
                            l1.get(mStateList)
                        }

                        if (buf != null) {
                            ins.close()
                            ops.close()
                        }
                        return
                    }
                } catch (e: UnknownHostException) {
                    e.printStackTrace()
                    Log.e(ContentValues.TAG, "debug112233: e1-->${e.printStackTrace()}")
                } catch (e: NetworkOnMainThreadException) {
                    Log.e(ContentValues.TAG, "debug112233: e2-->${e.printStackTrace()}")
                } catch (e: IOException) {
                    e.printStackTrace()
                    Log.e(ContentValues.TAG, "debug112233: e3-->${e.printStackTrace()}")
                } finally {
                    Log.e(ContentValues.TAG, "debug112233: test-->finally")
                }
            }
        }.start()
    }

    interface OnDeviceListener {
        fun get(b: Boolean,index: Int)
    }

    //获取设备状态
    fun sendDevice(bean: DeviceList ,queryIndex: Int, l: OnDeviceListener){
        Log.e(TAG, "sendDevice: 查询设备状态---》")
        when(bean.deviceType){
            2,3,9,11,13 ->{
                sendPC(bean.ip,8088,"test",l,queryIndex)
            }
            1 ->{
                sendTD(bean.switchGroup,bean.switchIndex,bean.com,bean.switchIP,bean.switchPort,l,queryIndex)
            }
            4,5 ->{
                sendKZ(bean.queryProtocol,bean.queryOpen,bean.switchIP,bean.switchPort,bean.com,l,queryIndex)
            }else->{

            }
        }

    }

    private fun sendTD(mctAddressNo: Int,SwitchIndex: Int,mCom: String,mIP: String,mPort: Int,ol: OnDeviceListener,queryIndex: Int){
        object : Thread() {
            override fun run() {
                //需要在子线程中处理的逻辑
                try {
                    //拼装规则字符串集合
                    val packet = byteArrayOf(0x55.toByte(), 0x01.toByte(), 0x10.toByte(), 0x00.toByte(), 0x00.toByte(), 0x00.toByte(), 0x00.toByte(), 0x66.toByte())
                    packet[1] = mctAddressNo.toByte()
                    packet[7] = (packet[7] + mctAddressNo.toByte() - 1.toByte()).toByte()
                    val mData = byteArrayOf(0xb1.toByte(), 0xac.toByte(),    0x00,0x01      ,0x01    ,(mCom.toInt() - 1).toByte())
                    val a = ControlDevice.addArray(mData, packet)
                    a[3] = (a.size + 2).toByte()
                    val l = CRC16Utils.getCrc16(a)
                    val msg = ControlDevice.addArray(a, l)

                    Log.e("debug112233-->setStatus:",CRC16Utils.byteTo16String(msg))

                    // 客户端 Socket 可以通过指定 IP 地址或域名两种方式来连接服务器端,实际最终都是通过 IP
                    // 地址来连接服务器
                    // 新建一个Socket，指定其IP地址及端口号
                    val socket = Socket(mIP, mPort)
                    val ops = socket.getOutputStream()
                    val ins = socket.getInputStream()
                    //新版中控服务器需要加头和尾
                    if (CommonLib.NEW_ZK){
                        ops.write(msg)
                    }else{
                        ops.write(packet)
                    }
                    val buf = ByteArray(32)
                    //获取数据赋值
                    while (ins.read(buf) > 0) {
                        Log.e(ContentValues.TAG, "debug112233: sendTD-->${CRC16Utils.byteTo16String(buf)}")
                        //去掉头部，只获取到Data部分
                        val mData = ByteArray(8)
                        System.arraycopy(buf, 6, mData, 0, 8);
                        Log.e(ContentValues.TAG, "debug112233: sendTD--1-->${CRC16Utils.byteTo16String(mData)}")
                        val buf5 = mData[5].toInt() and 0xff
                        val buf6 = mData[6].toInt() and 0xff
                        val states = buf6 + (buf5 shl 8)
                        val state = states shr SwitchIndex - 1 and 0x01

                        Log.e(ContentValues.TAG, "debug112233: sendTD--2-->${state}")
                        if (state > 0){
                            //设备开启状态
                            ol.get(true,queryIndex)
                        }else{
                            //设备关闭状态
                            ol.get(false,queryIndex)
                        }
                        if (buf != null) {
                            ins.close()
                            ops.close()
                        }
                        return
                    }
                } catch (e: UnknownHostException) {
                    e.printStackTrace()
                    Log.e(ContentValues.TAG, "sendTD: e-->${e.printStackTrace()}")
                } catch (e: NetworkOnMainThreadException) {
                    Log.e(ContentValues.TAG, "sendTD: e-->${e.printStackTrace()}")
                } catch (e: IOException) {
                    e.printStackTrace()
                    Log.e(ContentValues.TAG, "sendTD: e-->${e.printStackTrace()}")
                } finally {
                    Log.e(ContentValues.TAG, "debug112233: sendTD test-->finally")
                }
            }
        }.start()
    }

    private fun sendPC(ip: String, port: Int, act: String,ol: OnDeviceListener,queryIndex: Int) {
        val url = "http://" + ip + ":" + port + "/?act=" + act + "&r=" + (Math.random() * 10000).toInt()
        OkHttpUtil.get(url, object : Callback {
            override fun onFailure(call: Call, e: IOException) {
                ol.get(false,queryIndex)
            }

            @Throws(IOException::class)
            override fun onResponse(call: Call, response: Response) {
                if (response.isSuccessful) {
                    //开
                    ol.get(true,queryIndex)
                } else {
                    ol.get(false,queryIndex)
                }
            }
        })
    }

    private fun sendKZ(query: String,queryOpen: String,ip: String, port: Int,mCom: String,ol: OnDeviceListener,queryIndex: Int){
        object : Thread() {
            override fun run() {
                //需要在子线程中处理的逻辑
                try {

                    val mData = byteArrayOf(0xb1.toByte(), 0xac.toByte(), 0x00, 0x01, 0x01,(mCom.toInt() - 1).toByte())
                    val a: ByteArray = ControlDevice.addArray(mData,query.toByteArray())
                    a[3] = (a.size + 2).toByte()
                    val l = CRC16Utils.getCrc16(a)
                    val b: ByteArray = ControlDevice.addArray(a, l)


                    val socket = Socket(ip, port)
                    val ops = socket.getOutputStream()
                    val inD = socket.getInputStream()
                    //新版中控服务器需要加头和尾
                    if (CommonLib.NEW_ZK){
                        ops.write(b)
                    }else{
                        ops.write(query.toByteArray())
                    }

                    val buf = ByteArray(32)
                    while (inD.read(buf) > 0) {
                        val reQuery = ZhuanHuan.bytesToHexString(buf)
                        if (reQuery.contains(queryOpen.toLowerCase())) {
                            ol.get(true,queryIndex)
                        } else {
                            ol.get(false,queryIndex)
                        }
                        if (buf != null) {
                            inD.close()
                            ops.close()
                        }
                        return
                    }
                } catch (e: IOException) {
                    e.printStackTrace()
                }
            }
        }.start()
    }


}